import pprint
import re


import gradio as gr
import os

from moviepy import AudioFileClip
from pydub import AudioSegment

import single
import util
from gradio_client import Client
from my_audio_client import MyAudioClient
import caption_from_block

my_audio_client = MyAudioClient()
config = my_audio_client.load_config()
folder_path = util.get_folder_path()
# 指定音频文件所在的文件夹路径
audio_folder = f'{folder_path}/audio'




# 加载数据
def load_data():
    lines = my_audio_client.read_file()
    rows = my_audio_client.parse_data(lines)
    blocks = my_audio_client.get_blocks(rows)
    role_dict = my_audio_client.get_role_dict(blocks)
    return blocks, role_dict

blocks, role_dict = load_data()

# 获取该文件夹下所有音频文件的路径，并按文件名自然排序
audio_files = [os.path.join(audio_folder, f) for f in sorted(os.listdir(audio_folder), key=util.natural_sort_key) if
               f.endswith(('.mp3', '.wav', '.ogg'))]

if not audio_files:
    raise ValueError(f"指定的文件夹 '{audio_folder}' 中没有找到任何支持格式的音频文件 (.mp3, .wav, .ogg).")



current_playing_index = 0


def load_audio(file_path):
    """加载并返回音频文件路径"""
    global current_playing_index
    current_playing_index = audio_files.index(file_path)
    current_playing_md_value=f"当前播放：{current_playing_index}"
    audio_duration = util.get_audio_duration(file_path)

    pprint.pp(('load_audio',audio_files[current_playing_index]))
    return file_path,current_playing_md_value,audio_duration


def generate_audio():
    global current_playing_index
    config = my_audio_client.load_config()
    print('current_playing_index',current_playing_index)
    single.single_block(current_playing_index, use_moji=use_moji.value)
    return audio_files[current_playing_index],f"当前播放：{current_playing_index}"


def next_audio():
    """播放下一个音频文件"""
    global current_playing_index
    current_playing_index = (current_playing_index + 1) % len(audio_files)
    return audio_files[current_playing_index], audio_files[current_playing_index]


def crop_audio(start_time, end_time):
    print('crop_audio','start_time',start_time,'end_time',end_time)
    # 确保 start_time 和 end_time 不为 None
    if start_time is None or end_time is None:
        raise ValueError("start_time and end_time must not be None")
    # 确保 start_time 和 end_time 合理
    if start_time >= end_time:
        raise ValueError("start_time must be less than end_time")

    """剪裁音频文件"""
    global current_playing_index
    file_path = audio_files[current_playing_index]
    audio = AudioFileClip(file_path)
    cropped_audio = audio.subclipped(start_time, end_time)
    cropped_audio_path = f"{file_path}"
    cropped_audio.write_audiofile(cropped_audio_path)
    return cropped_audio_path, f"当前播放：{current_playing_index}"


def reload_audio_files():
    """重新加载音频文件列表"""
    global audio_files
    audio_files = [os.path.join(audio_folder, f) for f in sorted(os.listdir(audio_folder), key=util.natural_sort_key) if
                   f.endswith(('.mp3', '.wav', '.ogg'))]

    if not audio_files:
        raise ValueError(f"指定的文件夹 '{audio_folder}' 中没有找到任何支持格式的音频文件 (.mp3, .wav, .ogg).")

    # 更新文件选项
    audio_files_with_duration = []
    total_audio_duration = 0
    for audio_file in audio_files:
        duration = AudioFileClip(audio_file).duration
        # 获取文件名
        audio_name = os.path.basename(audio_file)
        audio_files_with_duration.append((f"{audio_name} - {duration:.2f} s", audio_file))
        total_audio_duration += duration
    total_audio_duration_markdown.value = f"总时长：{total_audio_duration / 60:.2f} m"

    # 使用 gr.update 更新 Radio 组件的选项
    return gr.update(choices=audio_files_with_duration)


# 添加音频聚合函数
def aggregate_audio_files():
    output_path = f"{folder_path}/aggregated_audio.wav"
    combined = AudioSegment.empty()
    for audio_file in audio_files:
        audio = AudioSegment.from_file(audio_file)
        combined += audio
    combined.export(output_path, format="wav")
    print(f"音频文件已成功聚合到 {output_path}")


def batch_generate_by_roles(selected_roles):
    """根据选择的角色批量生成音频"""
    if not selected_roles:
        return None
    
    results = []
    client = Client(config['gradio_url'])
    print('selected_roles',selected_roles)
    for role in selected_roles:
        if role in role_dict:
            for item in role_dict[role]:
                index = item['index']
                block = item['block']
                result = my_audio_client.geneAudio(block, index, client, use_moji=use_moji.value)
                if result is not None:
                    results.append(f"{audio_folder}/a{result}.wav")
    
    return results[-1] if results else None


with gr.Blocks() as demo:
    gr.Markdown("## 多音频文件播放器")
    with gr.Row():
        with gr.Column():
            audio_output = gr.Audio(label="正在播放的音频", type="filepath", autoplay=True)

    with gr.Row():
        with gr.Column():
            start_time_slider = gr.Slider(minimum=0, maximum=10, step=0.1, label="起始时间 (秒)", interactive=True)
            end_time_slider = gr.Slider(minimum=0,step=0.1, label="结束时间 (秒)", interactive=True,elem_id="end_time_slider")

    with gr.Row():
        use_moji = gr.Checkbox(
            label="使用Moji表情",
            value=True,
            info="控制是否在生成音频时使用Moji表情",
            elem_id="use_moji_checkbox",
            elem_classes="custom-checkbox",
            container=False,
            scale=1,
            min_width=100,
            interactive=True
        )

    with gr.Row():
        role_checkboxes = gr.CheckboxGroup(
            choices=list(role_dict.keys()),
            label="选择角色",
            info="选择要批量生成音频的角色"
        )

    with gr.Row():
        re_generate_button = gr.Button("重新生成")
        next_button = gr.Button("下一个")
        crop_button = gr.Button("剪裁音频")
        reload_button = gr.Button("重新加载")  # 添加重新加载按钮
        aggregate_button = gr.Button("音频聚合")
        batch_generate_button = gr.Button("批量生成")  # 添加批量生成按钮
        generate_caption_button = gr.Button("生成字幕")  # 添加生成字幕按钮

    with gr.Row():
        total_audio_duration_markdown = gr.Markdown("总时长：0 s")
        current_playing_md = gr.Markdown(f'当前播放：{current_playing_index}')
        caption_output = gr.Markdown("")  # 添加字幕输出区域



    def on_radio_change(file_radio):
        file_path, current_playing_md_value, audio_duration = load_audio(file_radio)
        # 更新 end_time_slider 的最大值为当前音频文件的时长
        return file_path, current_playing_md_value,gr.update(maximum=audio_duration), gr.update(maximum=audio_duration,value=audio_duration)

    # 获取音频文件的时长并将其添加到选项中
    audio_files_with_duration = []

    total_audio_duration = 0
    for audio_file in audio_files:
        duration = util.get_audio_duration(audio_file)
        # 获取文件名
        audio_name = os.path.basename(audio_file)
        audio_files_with_duration.append((f"{audio_name} - {duration:.2f} s", audio_file))
        total_audio_duration += duration

    total_audio_duration_markdown.value = f"总时长：{total_audio_duration / 60:.2f} m"

    # 创建带有音频时长的Radio组件
    file_radio = gr.Radio(choices=audio_files_with_duration, label="选择一个音频文件开始播放",
                          type="value",elem_id="file_radio") if audio_files else None

    if file_radio is not None:
        print('file_radio', file_radio)
        file_radio.change(fn=on_radio_change, inputs=[file_radio], outputs=[audio_output, current_playing_md, start_time_slider,end_time_slider])

    re_generate_button.click(fn=generate_audio, outputs=[audio_output, current_playing_md])
    next_button.click(fn=next_audio, inputs=[], outputs=[audio_output, file_radio])
    crop_button.click(fn=crop_audio, inputs=[start_time_slider, end_time_slider], outputs=[audio_output, current_playing_md])
    reload_button.click(fn=reload_audio_files, outputs=[file_radio])  # 将重新加载按钮与回调函数关联
    aggregate_button.click(fn=aggregate_audio_files, inputs=[])
    batch_generate_button.click(fn=batch_generate_by_roles, inputs=[role_checkboxes], outputs=[audio_output])  # 添加批量生成按钮事件

    # 添加生成字幕的处理函数
    def handle_generate_caption():
        try:
            srt_content = caption_from_block.generate_caption()
            return gr.update(value=f"字幕生成成功！内容预览：\n\n{srt_content[:500]}...")
        except Exception as e:
            return gr.update(value=f"字幕生成失败：{str(e)}")

    generate_caption_button.click(fn=handle_generate_caption, outputs=[caption_output])  # 添加生成字幕按钮事件

    demo.launch(allowed_paths=[audio_folder],server_port=7850)





with gr.Blocks() as demo:
    gr.Markdown("## 多音频文件播放器")
    with gr.Row():
        with gr.Column():
            audio_output = gr.Audio(label="正在播放的音频", type="filepath", autoplay=True)

    with gr.Row():
        with gr.Column():
            start_time_slider = gr.Slider(minimum=0, maximum=10, step=0.1, label="起始时间 (秒)", interactive=True)
            end_time_slider = gr.Slider(minimum=0,step=0.1, label="结束时间 (秒)", interactive=True,elem_id="end_time_slider")

    with gr.Row():
        use_moji = gr.Checkbox(
            label="使用Moji表情",
            value=True,
            info="控制是否在生成音频时使用Moji表情",
            elem_id="use_moji_checkbox",
            elem_classes="custom-checkbox",
            container=False,
            scale=1,
            min_width=100,
            interactive=True
        )

    with gr.Row():
        role_checkboxes = gr.CheckboxGroup(
            choices=list(role_dict.keys()),
            label="选择角色",
            info="选择要批量生成音频的角色"
        )

    with gr.Row():
        re_generate_button = gr.Button("重新生成")
        next_button = gr.Button("下一个")
        crop_button = gr.Button("剪裁音频")
        reload_button = gr.Button("重新加载")  # 添加重新加载按钮
        aggregate_button = gr.Button("音频聚合")
        batch_generate_button = gr.Button("批量生成")  # 添加批量生成按钮
        generate_caption_button = gr.Button("生成字幕")  # 添加生成字幕按钮

    with gr.Row():
        total_audio_duration_markdown = gr.Markdown("总时长：0 s")
        current_playing_md = gr.Markdown(f'当前播放：{current_playing_index}')
        caption_output = gr.Markdown("")  # 添加字幕输出区域




    def on_radio_change(file_radio):
        file_path, current_playing_md_value, audio_duration = load_audio(file_radio)
        # 更新 end_time_slider 的最大值为当前音频文件的时长
        return file_path, current_playing_md_value,gr.update(maximum=audio_duration), gr.update(maximum=audio_duration,value=audio_duration)

    # 获取音频文件的时长并将其添加到选项中
    audio_files_with_duration = []

    total_audio_duration = 0
    for audio_file in audio_files:
        duration = util.get_audio_duration(audio_file)
        # 获取文件名
        audio_name = os.path.basename(audio_file)
        audio_files_with_duration.append((f"{audio_name} - {duration:.2f} s", audio_file))
        total_audio_duration += duration

    total_audio_duration_markdown.value = f"总时长：{total_audio_duration / 60:.2f} m"

    # 创建带有音频时长的Radio组件
    file_radio = gr.Radio(choices=audio_files_with_duration, label="选择一个音频文件开始播放",
                          type="value",elem_id="file_radio") if audio_files else None

    if file_radio is not None:
        print('file_radio', file_radio)
        file_radio.change(fn=on_radio_change, inputs=[file_radio], outputs=[audio_output, current_playing_md, start_time_slider,end_time_slider])

    re_generate_button.click(fn=generate_audio, outputs=[audio_output, current_playing_md])
    next_button.click(fn=next_audio, inputs=[], outputs=[audio_output, file_radio])
    crop_button.click(fn=crop_audio, inputs=[start_time_slider, end_time_slider], outputs=[audio_output, current_playing_md])
    reload_button.click(fn=reload_audio_files, outputs=[file_radio])  # 将重新加载按钮与回调函数关联
    aggregate_button.click(fn=aggregate_audio_files, inputs=[])
    batch_generate_button.click(fn=batch_generate_by_roles, inputs=[role_checkboxes], outputs=[audio_output])  # 添加批量生成按钮事件

    # 添加生成字幕的处理函数
    def handle_generate_caption():
        try:
            srt_content = caption_from_block.generate_caption()
            return gr.update(value=f"字幕生成成功！内容预览：\n\n{srt_content[:500]}...")
        except Exception as e:
            return gr.update(value=f"字幕生成失败：{str(e)}")

    generate_caption_button.click(fn=handle_generate_caption, outputs=[caption_output])  # 添加生成字幕按钮事件

    demo.launch(allowed_paths=[audio_folder],server_port=7850)




